package com.catazzz.springbootstudy.common.security;

import com.catazzz.springbootstudy.common.exception.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * @作者: Tao
 * @日期: 2025/1/8
 * @时间: 09:59
 * @描述: 自定义的认证失败处理类 <br><pre>
 *          继承自Spring Security的简单URL认证失败处理器
 *          用于在用户认证失败时，返回更加友好的JSON响应信息
 */
//@Component
public class CustomerAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    /**
     * 处理认证失败的逻辑
     *
     * @param request 认证失败时的HTTP请求对象，用于获取请求信息
     * @param response 认证失败时的HTTP响应对象，用于向客户端发送响应信息
     * @param exception 认证失败的异常对象，用于判断认证失败的原因
     * @throws IOException 当写入响应流时可能抛出的异常
     * @throws ServletException 当处理认证失败时可能抛出的Servlet异常
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        // 设置响应的字符编码和内容类型，确保响应信息的正确性和兼容性
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);

        // 初始化一个错误的响应结果对象
        Result<Object> result = Result.error();

        // 根据不同的异常类型，设置具体的错误信息
        if (exception instanceof UsernameNotFoundException) {
            result = Result.error("用户未找到");
        } else if (exception instanceof BadCredentialsException) {
            result = Result.error("密码错误");
        }

        // 将结果对象序列化为JSON字符串，并写入响应流中
        response.getWriter().write(new ObjectMapper().writeValueAsString(result));
    }
}

